/*
 * 文 件 名:  ObjectFactory2.java
 * 版    权:  Copyright YYYY-YYYY,  All rights reserved
 * 描    述:  <描述>
 * 创 建 人:   fengqianqian@itany.com
 * 创建时间:  5-24
 */
package org.wanho.rent.factory;

import java.io.File;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * <一句话功能简述>
 *  利用反射技术, 依赖自定义注解的工厂, 脱离了配置文件
 * @author  
 * @version  [V1.00, 5-24]
 * @see  [相关类/方法]
 * @since V1.00
 */
public class AutoObjectFactory {

	// 获取运行时类加载路径(普通java项目时使用)
//	private static final File basePath = new File(ObjectFactory.class.getClassLoader().getResource(".").getPath());
	// 获取运行时类加载路径(javaWeb项目时使用)
	private static final File basePath = new File(ObjectFactory.class.getClassLoader().getResource("/").getPath());

	private static final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();

	private static final Map<String, Object> objs = new HashMap<String, Object>();
	
	static {
		try {
			System.out.println("工厂初始化开始...");
			check(basePath);
			System.out.println("工厂初始化结束");
			//Class加载,且对象创建完成后,自动注入
			autowired(null);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new ExceptionInInitializerError("工厂初始化失败");
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		}
	}

	private static void check(File file) throws ClassNotFoundException {

		// 递归
		if (file.isDirectory()) {
			File[] fs = file.listFiles();
			for (File ff : fs) {
				check(ff);
			}
		}

		String path = file.getAbsolutePath();

		// 只获取".class"结尾的文件路径
		if (path.endsWith(".class")) {
			System.out.println("检测到class文件: " + path);

			// 将文件路径中"类加载路径"部分干掉, 只保留从包路径
			String className = path.replace(basePath.getAbsolutePath(), "");
			System.out.println("文件包路径: " + className);

			// 将末尾的".class"去掉
			className = className.substring(1, className.lastIndexOf(".class"));

			// 将字符串中文件分割符替换成".", 最终结果就是得到"包名.类名", 即完整类名
			className = className.replaceAll("/|\\\\", ".");

			System.out.println("类名: " + className);

			// 根据类名获取Class对象
			Class<?> c = Class.forName(className);

			// 获取Class对象的注解
			MyComponet annotation = (MyComponet) c.getAnnotation(MyComponet.class);

			// 如果能够得到注解对象
			if (null != annotation) {
				System.out.println("有注解的类: " + className);

				// 获取注解对象的value值, 做为工厂集中的key使用
				String key = annotation.value();

				// 如果没有获取到注解的value值, 将注解所在类的简单类名首字母转小写后当做key使用
				if (null == key || "".equals(key)) {
					String simpleClassName = c.getSimpleName();
					key = simpleClassName.substring(0, 1).toLowerCase() + simpleClassName.substring(1);
				}
				System.out.println("工厂获取对象key: " + key);
				classes.put(key, c);
				try {
					objs.put(key, c.newInstance());
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
			System.out.println("---------------------------------------------------------");
		}
		
	}

	public static Object getObject(String key) {
		Object obj = objs.get(key);
		if (null == obj) {
			if (null == obj) {
				Class<?> c = classes.get(key);
				if (null != c) {
					try {
						obj = c.newInstance();
						objs.put(key, obj);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		}

		return obj;
	}
	
	/**
	 * 自动注入组件中的依赖属性
	 */
	private static void autowired(Object obj){
		Set<String> keySet = classes.keySet();
		for (String key : keySet) {
			Class<?> c = classes.get(key);
			Object mainObj = objs.get(key);
			autowiredToMainObj(c, mainObj);
		}
	}
	//为mainObj的依赖属性自动注入
	private static void autowiredToMainObj(Class<?> c, Object mainObj){
		//获取组件中所有的属性
		Field[] fields = c.getDeclaredFields();
		if(null != fields){//有属性
			for (Field field : fields) {
				//如果有自动注入的注解,则自动注入
				Autowired aw = field.getAnnotation(Autowired.class);
				if(null != aw){
					String objKey = aw.value();//获取注入对象的key
					//必须要有objKey
					if(null != objKey && !"".equals(objKey.trim())){
						Object value = objs.get(objKey);//属性值
						field.setAccessible(true);
						try {
							field.set(mainObj, value);
							System.out.println("信息: 类[" + c + "]中的属性[" + field.getName() + "]的@Autowired成功!");
						} catch (IllegalAccessException e) {
							e.printStackTrace();
							System.err.println("严重: 类[" + c + "]中的属性[" + field.getName() + "]的@Autowired失败: " + e.getMessage());
						}
					}else{
						System.err.println("严重: 类[" + c + "]中的属性[" + field.getName() + "]的@Autowired未配置key");
					}
				}
			}
		}
	}
	
	/**
	 * 自动注入Controller中的依赖属性
	 */
	public static void autowiredController(Object controller){
		autowiredToMainObj(controller.getClass(), controller);
	}
	
}

